/*
 * ComponentDelegate.h  0.4.0 / Nov 17, 2010
 *
 * Copyright (c) 2010 - 2011, cute4j.com and contributors.
 *
 * This software is licensed under the LGPL version 2.1 license.
 * A copy of this license is included in the file LICENSE-LGPL.txt.
 */
#ifndef COMPONENTDELEGATE_H
#define COMPONENTDELEGATE_H

#include "Cute4jSwing.h"

#include "QObjectDelegate.h"
#include "SwingUtilitiesDelegate.h"

// ComponentDelegate Class. ----------------------------------------------------

class ContainerDelegate;

/*!
 * \brief Component Delegate.
 *
 * \author Slobodan Vrkacevic
 * \version 0.4.0
 */
class CUTE4J_EXPORT ComponentDelegate : public QObjectDelegate
{
  Q_OBJECT
protected:
  ComponentDelegate(JNIEnv *env, jobject obj, QWidget *widget);
  ComponentDelegate(JNIEnv *env, jobject obj);
private:
  friend class ActionComponentDelegate; // uses the following constructor
  ComponentDelegate(JNIEnv *env, jobject obj, QAction *action);
protected:
  virtual ~ComponentDelegate();
public slots: // native calls
  virtual void setVisible(JNIEnv *env, jboolean visible);
  virtual void showWindow(JNIEnv *env);
  virtual void setEnabled(JNIEnv *env, jboolean enabled); 
  virtual void setFocusable(JNIEnv *env, jboolean focusable);
  virtual void requestFocus(JNIEnv *env);
  virtual void setLocation(JNIEnv *env, jint x, jint y);
  virtual jobject getPreferredSize(JNIEnv *env);
  virtual void setSize(JNIEnv *env, jint width, jint height);
  virtual void setMaximumSize(JNIEnv *env, jint width, jint height);
  virtual void setMinimumSize(JNIEnv *env, jint width, jint height);
  virtual void setFixedSize(JNIEnv *env, jint width, jint height);
  virtual void setBounds(JNIEnv *env, jint x, jint y, jint width, jint height);
  virtual jobject getBackground(JNIEnv *env, jclass colorClass);
  virtual void setBackground(JNIEnv *env, jint argb);
  virtual void setNullBackground(JNIEnv *env);
  virtual jobject getForeground(JNIEnv *env, jclass colorClass);
  virtual void setForeground(JNIEnv *env, jint argb);
  virtual void setNullForeground(JNIEnv *env);
  virtual void setOpaque(JNIEnv *env, jboolean opaque);
  virtual jobject getFont(JNIEnv *env, jclass fontClass);
  virtual void setFont(JNIEnv *env, jobject font);
  virtual void setStyleSheet(JNIEnv *env, jstring styleSheetText);
  virtual void setStyleSheetProperties(JNIEnv *env);
  virtual void removeStyleSheetProperties(JNIEnv *env);
  virtual jint getCursor(JNIEnv *env);
  virtual void setCursor(JNIEnv *env, jint type);
  virtual void repaint(JNIEnv *env);
  virtual void repaint(JNIEnv *env, jint x, jint y, jint width, jint height);
  virtual void update(JNIEnv *env);
  virtual void update(JNIEnv *env, jint x, jint y, jint width, jint height);
  virtual void setUpdatesEnabled(JNIEnv *env, jboolean enabled);
  virtual void polish(JNIEnv *env);
  virtual void setComponentOrientation(JNIEnv *env, jint orientation);
  virtual void setToolTipText(JNIEnv *env, jstring text);
  virtual void setStatusTipText(JNIEnv *env, jstring text);
  virtual void setWhatsThisText(JNIEnv *env, jstring text);
  virtual void setEnabledEvents(JNIEnv *env, jlong events);
  virtual void paintComponent(JNIEnv *env, jlong graphicsDelegate);
public: // native calls
  static void initialize(JNIEnv *env, jclass cls);
  static jlong newInstance(JNIEnv *env, jobject obj);
public: // native callbacks
  void visibleChanged(bool visible);
  void enabledChanged(bool enabled);
  void positionChanged(jint x, jint y);
  void sizeChanged(jint width, jint height);
  void paint(jint x, jint y, jint width, jint height);
  void styleChanged();
  void styleSheetChanged(bool removed);
  void focusGained();
  void focusLost();
  void keyPressed(jint modifiers, jint keyCode, jchar keyChar);
  void keyReleased(jint modifiers, jint keyCode, jchar keyChar);
  void keyTyped(jint modifiers, jint keyCode, jchar keyChar);
  void mouseEntered(jint button, jint modifiers, jint x, jint y);
  void mouseExited(jint button, jint modifiers, jint x, jint y);
  void mousePressed(jint button, jint modifiers, jint x, jint y);
  void mouseReleased(jint button, jint modifiers, jint x, jint y);
  void mouseClicked(jint button, jint modifiers, jint x, jint y);
  void mouseDoubleClicked(jint button, jint modifiers, jint x, jint y);
  void contextMenuTriggered(jint reason, jint modifiers, jint x, jint y,
                            jint globalX, jint globalY);
  void mouseMoved(jint button, jint modifiers, jint x, jint y);
  void mouseDragged(jint button, jint modifiers, jint x, jint y);
  void mouseWheelMoved(jint modifiers, jint x, jint y, jint wheelRotation);
  QSize getPreferredSize();
  jstring getToolTipText(int x, int y);
public:
  virtual void setParentDelegate(ContainerDelegate *parentDelegate);
  virtual QWidget *qWidget();
  virtual QAction *qAction();
public:
  inline bool eventFilterEnabled() const;
  inline void setEventFilterEnabled(bool enabled);
public:
  virtual void destroy(JNIEnv *env, bool notify = false);
protected:
  friend class QWidgetActionAdapter; // uses widgetActionDeleted function member
  virtual void widgetActionDeleted(QAction *action);
  virtual bool filterEvent(QObject *obj, QEvent *e);
  virtual bool filterShowEvent(QObject *obj, QShowEvent *e);
  virtual bool filterHideEvent(QObject *obj, QHideEvent *e);
  virtual bool filterEnabledChangeEvent(QObject *obj, QEvent *e);
  virtual bool filterStyleChangeEvent(QObject *obj, QEvent *e);
  virtual bool filterResizeEvent(QObject *obj, QResizeEvent *e);
  virtual bool filterMoveEvent(QObject *obj, QMoveEvent *e);
  virtual bool filterFocusGainedEvent(QObject *obj, QFocusEvent *e);
  virtual bool filterFocusLostEvent(QObject *obj, QFocusEvent *e);
  virtual bool filterKeyPressedEvent(QObject *obj, QKeyEvent *e);
  virtual bool filterKeyReleasedEvent(QObject *obj, QKeyEvent *e);
  virtual bool filterKeyTypedEvent(QObject *obj, QKeyEvent *e);
  virtual bool filterMouseEnterEvent(QObject *obj, QMouseEvent *e);
  virtual bool filterMouseMoveEvent(QObject *obj, QMouseEvent *e);
  virtual bool filterMouseLeaveEvent(QObject *obj, QMouseEvent *e);
  virtual bool filterMousePressedEvent(QObject *obj, QMouseEvent *e);
  virtual bool filterMouseReleasedEvent(QObject *obj, QMouseEvent *e);
  virtual bool filterMouseClickedEvent(QObject *obj, QMouseEvent *e);
  virtual bool filterMouseDoubleClickedEvent(QObject *obj, QMouseEvent *e);
  virtual bool filterMouseWheelEvent(QObject *obj, QWheelEvent *e);
  virtual bool filterToolTipEvent(QObject *obj, QHelpEvent *e);
  virtual bool filterWhatsThisEvent(QObject *obj, QHelpEvent *e);
  virtual bool filterContextMenuEvent(QObject *obj, QContextMenuEvent *e);
  virtual void filterEnabledEvents();
  virtual QWidget *paintingWidget();
protected:
  inline jlong enabledEvents() const;
  inline bool eventEnabled(jlong eventMask) const;
  inline QEvent *currentEvent() const;
  inline int previousEventType() const;
  inline ContainerDelegate *parentDelegate() const;
protected:
  inline static jmethodID createMID();
protected:
  virtual jfieldID delegatePointerFID() const;
  virtual bool eventFilter(QObject *obj, QEvent *e);
private:
  void fillStyleSheetProperties(JNIEnv *env, const QVariant *value);
private:
  bool m_eventFilterEnabled;
  jlong m_enabledEvents;
  QEvent *m_currentEvent;
  QPaintEvent *m_paintEvent;
  int m_previousEventType;
  int m_previousKey;
  Qt::MouseButton m_previousMouseButton;
  int m_previousMouseX;
  int m_previousMouseY;
  ContainerDelegate *m_parentDelegate;
  QWidget *m_widget;
  QAction *m_action;
private:
  static jclass sm_abstractDisposableClass;
  static jmethodID sm_classGetNameMID;
  static jfieldID sm_delegateFID;
  static jmethodID sm_getPreferredSizeMID;
  static jmethodID sm_visibleChangedMID;
  static jmethodID sm_enabledChangedMID;
  static jmethodID sm_sizeChangedMID;
  static jmethodID sm_positionChangedMID;
  static jmethodID sm_paintMID;
  static jmethodID sm_styleChangedMID;
  static jmethodID sm_styleSheetChangedMID;
  static jmethodID sm_focusGainedMID;
  static jmethodID sm_focusLostMID;
  static jmethodID sm_keyPressedMID;
  static jmethodID sm_keyReleasedMID;
  static jmethodID sm_keyTypedMID;
  static jmethodID sm_mouseEnteredMID;
  static jmethodID sm_mouseExitedMID;
  static jmethodID sm_mousePressedMID;
  static jmethodID sm_mouseReleasedMID;
  static jmethodID sm_mouseClickedMID;
  static jmethodID sm_mouseDoubleClickedMID;
  static jmethodID sm_contextMenuTriggeredMID;
  static jmethodID sm_mouseMovedMID;
  static jmethodID sm_mouseDraggedMID;
  static jmethodID sm_mouseWheelMovedMID;
  static jmethodID sm_getToolTipTextMID;
  static jmethodID sm_createMID;
public:
  static const QVariant STYLE_SHEET_PROPERTY_VALUE;
};

// ComponentDelegate :: Public Inline Member Functions. ------------------------

/*!
 * \brief Returns \c true if filtering events.
 *
 * \return \c true if filtering events
 */
inline bool ComponentDelegate::eventFilterEnabled() const
{
  return m_eventFilterEnabled;
}

/*!
 * \brief Enables/disables event filter.
 *
 * \param enabled \c true if enabled
 */
inline void ComponentDelegate::setEventFilterEnabled(bool enabled)
{
  m_eventFilterEnabled = enabled;
}

// ComponentDelegate :: Protected Inline Member Functions. ---------------------

/*!
 * \brief Returns enabled events.
 *
 * \return enabled events
 */
inline jlong ComponentDelegate::enabledEvents() const
{
  return m_enabledEvents;
}

/*!
 * \brief Tests if the specified event is enabled.
 *
 * \param eventMask the event to test
 *
 * \return \c true if event is enabled
 */
inline bool ComponentDelegate::eventEnabled(jlong eventMask) const
{
  return (m_enabledEvents & eventMask);
}

/*!
 * \brief Returns current event.
 *
 * \return current event
 */
inline QEvent *ComponentDelegate::currentEvent() const
{
  return m_currentEvent;
}

/*!
 * \brief Returns previous event type.
 *
 * \return previous event type
 */
inline int ComponentDelegate::previousEventType() const
{
  return m_previousEventType;
}

/*!
 * \brief Returns parent delegate.
 *
 * \return parent delegate
 */
ContainerDelegate *ComponentDelegate::parentDelegate() const
{
  return m_parentDelegate;
}

// ComponentDelegate :: Protected Static Inline Member Function. ---------------

/*!
 * \brief Returns createMID.
 *
 * \return createMID
 */
inline jmethodID ComponentDelegate::createMID()
{
  return sm_createMID;
}

// Macro Definitions. ----------------------------------------------------------

#define COMPONENT_CAST(delegate) \
    (reinterpret_cast<ComponentDelegate *>(delegate))

#define COMPONENT_DELEGATE COMPONENT_CAST(delegate)

#endif // COMPONENTDELEGATE_H
